// mongoose setup
require( '../../../config' );
var sinon   = require('sinon'),
    sinonSandbox,
    nock        = require('nock'),
    Promise  = require('promise'),
    accesstokenDao = require( '../../../../app/components/backend/db/daos/accesstoken'),
    accesstokenModels = require('../../../../app/components/backend/db/models/accesstoken'),
    util = require('../../../../app/components/backend/util'),
    weixin = require('../../../../app/components/backend/util').weixin,
    assert = require('assert'),
    testData = {
      access_token: 'BYEsg8wnKAM0d_7uxOjq7E7LgTeCPBw-FQa_-NVUviAMjMSKFD-85Z7rfrJa9vLX4-g3IpDJeKh6EpAp231gofjGokYc23nC9oQ4FX_k2Cs',
      create_time: 1440009999000 // 2015/08/20
    },
    mockAccessTokenFromWeixin = {
      expires_in: 7200,
      access_token: 'XXXXXXXXXXM0d_7uxOjq7E7LgTeCPBw-FQa_-NVUviAMjMSKFD-85Z7rfrJa9vLX4-g3IpDJeKh6EpAp231gofjGokYc23nC9oQ4FX_k2Cs'
    };

describe('app/components/backend/util/weixin', function() {

  // 测试前置处理
  beforeEach(before);

  // 测试后置处理
  afterEach(after);

  describe('#weixin.getAccessToken()', function () {
    it('[weixin.getAccessToken.Nor.01].token已经过期, 从wexin取得新token, 并存入数据库]. ', function () {
      var outDateToken = {
        access_token: 'BYEsg8wnKAM0d_7uxOjq7E7LgTeCPBw-FQa_-NVUviAMjMSKFD-85Z7rfrJa9vLX4-g3IpDJeKh6EpAp231gofjGokYc23nC9oQ4FX_k2Cs',
        create_time: 0 // 1970/01/01
      };

      return accesstokenDao.upsert({}, outDateToken) // token已过期
        .then(weixin.getAccessToken) // 刷新并获取新的token
        .then(function (accessToken) {

          // 数据库保存了从微信取得的最新token
          assert.equal(accessToken.access_token, mockAccessTokenFromWeixin.access_token);

          // 新的token是没有过期的
          assert.ok(Date.now() - accessToken.create_time < util.config.access_token_expires_in);
          return Promise.resolve();
        });
    });

    it('[weixin.getAccessToken.Nor.02.数据库中没有token.从微信获取新的token并插入数据库]. ', function () {
      return weixin.getAccessToken() // 从微信获取新的token并插入数据库
        .then(function (accessToken) {
          assert.ok(accessToken.create_time - testData.create_time > util.config.access_token_expires_in);
          assert.equal(accessToken.access_token, mockAccessTokenFromWeixin.access_token);
          assert.ok(Date.now() - accessToken.create_time < util.config.access_token_expires_in);
          return Promise.resolve();
        });
    });

    it('[weixin.getAccessToken.Nor.03.token没过期. 直接取得数据库的值]. ', function () {
      testData.create_time = Date.now();
      return accesstokenDao.upsert({}, testData) // token已过期
        .then(weixin.getAccessToken) // 刷新并获取新的token
        .then(function (accessToken) {
          assert.equal(accessToken.create_time, testData.create_time);
          assert.equal(accessToken.access_token, testData.access_token);
          assert.ok(Date.now() - accessToken.create_time < util.config.access_token_expires_in);
          return Promise.resolve();
        });
    });
  });
});

function mockGetAccessTokenFromWeixin () {
  return new Promise(function(resolve, reject) {

    // 模拟请求, nock会把执行过的interceptor从list中remove掉; 所以对于一个url的多次请求要多次设置
    nock('https://api.weixin.qq.com').get('/cgi-bin/token').query({

      // Mock token
      grant_type: 'client_credential',
      appid     : util.config.appid,
      secret    : util.config.appsecret
    }).reply(200, mockAccessTokenFromWeixin);
    resolve();
  });
};

function before () {
  return mockGetAccessTokenFromWeixin().then(function() {
    sinonSandbox = sinon.sandbox.create();
    return Promise.resolve();
  });
}

function after () {

  // 复位
  if (sinonSandbox) sinonSandbox.restore();

  // 清空weixinusers collection
  accesstokenModels.remove({}, function(err) {
    if (err) throw new Error(err);
    console.log('\n>>>>>>>>>> collection removed');
  });
}